﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ThreeNaturalSplines : MonoBehaviour {
	public static ThreeNaturalSplines Instance;

	public DrawLine drawLine;
	public float interval;
	private int n;
	private float length;
	private List<Vector2> p;
	private List<Vector2> pointList;
	private float[] a;
	private float[] h;
	private float[] c;
	private float[] d;
	private float[] b;
	private float[] S__;
	private float S_;
	private float S;
	private float t;

	private void Awake() {
		Instance = this;
	}

	// Start is called before the first frame update
	void Start() {
		n = RandomPointList.Instance.n;
		length = n * RandomPointList.Instance.interval;
		pointList = new List<Vector2>();
	}

	// Update is called once per frame
	void Update() {

	}

	public void ThreeNaturalSplinesAlgorithm() {
		p = RandomPointList.Instance.randomPointList;
		pointList.Clear();

		a = new float[n + 1];
		b = new float[n + 1];
		c = new float[n + 1];
		d = new float[n + 1];
		h = new float[n + 1];
		S__ = new float[n + 1];

		for (int k = 0; k <= n - 1; k++) h[k] = p[k + 1].x - p[k].x;
		a[1] = 2 * (h[0] + h[1]);
		for (int k = 2; k < n; k++) a[k] = 2 * (h[k - 1] + h[k]) - h[k - 1] * h[k - 1] / a[k - 1];
		for (int k = 1; k <= n; k++) c[k] = (p[k].y - p[k - 1].y) / h[k - 1];
		for (int k = 1; k <= n - 1; k++) d[k] = 6 * (c[k + 1] - c[k]);
		b[1] = d[1];
		for (int k = 2; k <= n - 1; k++) b[k] = d[k] - b[k - 1] * h[k - 1] / a[k];
		S__[n - 1] = b[n - 1] / a[n - 1];
		for (int k = n - 2; k > 0; k--) S__[k] = (b[k] - h[k] * S__[k + 1]) / a[k];
		S__[0] = 0; S__[n] = 0;
		for (int k = 0; k < n; k++) {
			for (float x = p[k].x; x <= p[k + 1].x; x += interval) {
				S_ = c[k + 1] - S__[k + 1] * h[k] / 6 - S__[k] * h[k] / 3;
				t = x - p[k].x;
				S = p[k].y + S_ * t + S__[k] * t * t / 2 + (S__[k + 1] - S__[k]) * t * t * t / (6 * h[k]);
				//System.Threading.Thread.Sleep(10);
				pointList.Add(new Vector2(x, S));
				//drawLine.UpdateLine();
			}
		}
		drawLine.pointList = pointList;
	}
}
